/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef NATIVE_RDB_ABS_SHARED_RESULT_SET_H
#define NATIVE_RDB_ABS_SHARED_RESULT_SET_H

#include <memory>
#include <string>
#include <thread>
#include <vector>

#include "abs_result_set.h"
#include "shared_result_set.h"

namespace OHOS {
namespace NativeRdb {
/**
 * The AbsResultSet class of RDB.
 * Provides methods for accessing a database result set generated by querying the database.
 */
class API_EXPORT AbsSharedResultSet : public AbsResultSet, public SharedResultSet {
public:
    /**
     * @brief Constructor.
     */
    API_EXPORT AbsSharedResultSet();

    /**
     * @brief Constructor.
     *
     * A parameterized constructor used to create an AbsSharedResultSet instance.
     *
     * @param tableName Indicates the table name of the database.
     */
    API_EXPORT explicit AbsSharedResultSet(std::string name);

    /**
     * @brief Destructor.
     */
    API_EXPORT virtual ~AbsSharedResultSet();

    /**
     * @brief Obtains the value of the specified column in the current row as string.
     *
     * The implementation class determines whether to throw an exception if the value of the specified column
     * in the current row is null or the specified column is not of the string type.
     *
     * @param columnIndex Indicates the specified column index, which starts from 0.
     *
     * @return Returns the value of the specified column as a string.
     */
    API_EXPORT int GetString(int columnIndex, std::string &value) override;

    /**
     * @brief Obtains the value of the specified column in the current row as assets.
     *
     * The implementation class determines whether to throw an exception if the value of the specified column
     * in the current row is null or the specified column is not of the double type.
     *
     * @param columnIndex Indicates the specified column index, which starts from 0.
     *
     * @return Returns the value of the specified column as a double.
     */
    API_EXPORT int Get(int32_t col, ValueObject &value) override;

    /**
     * @brief Get the size of blob or text.
     *
     * @param columnIndex Indicates the zero-based index of the target column.
     */
    API_EXPORT int GetSize(int columnIndex, size_t &size) override;

    /**
     * @brief Obtains data type of the given column's value.
     *
     * @param columnIndex Indicates the specified column index, which starts from 0.
     *
     * @return Returns column value type.
     */
    API_EXPORT int GetColumnType(int columnIndex, ColumnType &columnType) override;

    /**
     * @brief Move the cursor to an absolute position.
     *
     * @param position Indicates the specified column index, which starts from 0.
     *
     * @return Returns whether the requested move succeeded.
     */
    API_EXPORT int GoToRow(int position) override;

    /**
     * @brief Obtains the number of rows in the result set.
     */
    API_EXPORT int GetRowCount(int &count) override;

    /**
     * @brief Obtains a block from the {@link SharedResultSet}.
     */
    API_EXPORT std::shared_ptr<AppDataFwk::SharedBlock> GetBlock() override;

    /**
     * @brief Called when the position of the result set changes.
     */
    API_EXPORT int32_t OnGo(int oldRowIndex, int newRowIndex) override;

    /**
     * @brief Allocates a new shared block to an {@link AbsSharedResultSet}
     */
    API_EXPORT virtual void SetBlock(AppDataFwk::SharedBlock *block);

    /**
     * @brief Closes the result set.
     *
     * Calling this method on the result set will release all of its resources and makes it ineffective.
     */
    API_EXPORT int Close() override;

    /**
     * @brief Checks whether an {@code AbsSharedResultSet} object contains shared blocks.
     */
    API_EXPORT bool HasBlock();

protected:
    int CheckState(int columnIndex);
    void ClearBlock();
    void ClosedBlock();
    virtual void Finalize();

    // The default position of the cursor
    static const int INIT_POS = -1;
private:
    int GetCustomerValue(int index, ValueObject &value, AppDataFwk::SharedBlock *block);
    int UpdateBlockPos(int position, int rowCnt);

    static const size_t DEFAULT_BLOCK_SIZE = 2 * 1024 * 1024;
    friend class ISharedResultSetStub;
    friend class ISharedResultSetProxy;
    // The SharedBlock owned by this AbsSharedResultSet
    std::shared_ptr<AppDataFwk::SharedBlock> sharedBlock_ = nullptr;
    std::string sharedBlockName_ = "defaultSharedBlockName";
    // If the shared memory application fails for the first time, GetBlock() returns nullptr forever
    bool lowMem_ = false;
};
} // namespace NativeRdb
} // namespace OHOS

#endif